/****************************************************************************
 * Copyright (C) 2009-2013 GGA Software Services LLC
 *
 * This file is part of Imago OCR project.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#include "probability_separator.h"

using namespace imago;

// Probabilities retrieved for vector normalized with largest value in contour
double jointPSMax[8][10] = {
	{0.0175,    0.0205,    0.0147,    0.0171,    0.0144,    0.0178,    0.0146,    0.0082,    0.0097,    0.0119},
    {0.0034,    0.0059,    0.0107,    0.0141,    0.0179,    0.0115,    0.0079,    0.0053,    0.0056,    0.0051},
    {0.0303,    0.0072,    0.0132,    0.0157,    0.0219,    0.0207,    0.0132,    0.0115,    0.0129,    0.0190},
    {0.0046,    0.0068,    0.0082,    0.0118,    0.0104,    0.0104,    0.0097,    0.0074,    0.0071,    0.0051},
    {0.0160,    0.0321,    0.0225,    0.0268,    0.0243,    0.0147,    0.0150,    0.0097,    0.0075,    0.0079},
    {0.0032,    0.0090,    0.0093,    0.0119,    0.0119,    0.0110,    0.0081,    0.0096,    0.0071,    0.0041},
    {0.0207,    0.0096,    0.0168,    0.0274,    0.0280,    0.0240,    0.0166,    0.0127,    0.0121,    0.0171},
    {0.0031,    0.0097,    0.0085,    0.0090,    0.0116,    0.0099,    0.0065,    0.0069,    0.0044,    0.0026}
};

double jointPGMax[8][10] = {
	{0.0449,    0.0146,    0.0105,    0.0077,    0.0095,    0.0086,    0.0108,    0.0155,    0.0146,    0.0255},
    {0.0198,    0.0138,    0.0074,    0.0034,    0.0052,    0.0045,    0.0050,    0.0050,    0.0045,    0.0081},
    {0.0394,    0.0093,    0.0065,    0.0076,    0.0089,    0.0127,    0.0114,    0.0074,    0.0059,    0.0169},
    {0.0182,    0.0091,    0.0059,    0.0040,    0.0038,    0.0079,    0.0079,    0.0079,    0.0105,    0.0146},
    {0.0934,    0.0279,    0.0115,    0.0096,    0.0122,    0.0098,    0.0122,    0.0160,    0.0186,    0.0267},
    {0.0213,    0.0114,    0.0074,    0.0046,    0.0033,    0.0048,    0.0064,    0.0045,    0.0050,    0.0088},
    {0.0428,    0.0108,    0.0083,    0.0086,    0.0100,    0.0146,    0.0095,    0.0079,    0.0088,    0.0160},
    {0.0219,    0.0103,    0.0062,    0.0029,    0.0067,    0.0079,    0.0107,    0.0057,    0.0071,    0.0133}
};

double jointPS[8][10] = {
	{0.01181986,  	0.01820985,  	0.02028161,  	0.01691587,  	0.01083930,  	0.005411561,  	0.002127198,  	0.0006688037,  	0.0001753944,  	4.426793e-05},
	{0.01462826,  	0.02265224,  	0.02542391,  	0.02143222,  	0.01392735,  	0.007083110,  	0.002855894,  	0.0009312940,  	0.0002564298,  	6.638127e-05},
	{0.01719284,  	0.02667401,  	0.03002907,  	0.02543514,  	0.01664895,  	0.008560408,  	0.003509003,  	0.0011733366,  	0.0003347424,  	8.945728e-05},
	{0.01895981,  	0.02917792,  	0.03245686,  	0.02707040,  	0.01741079,  	0.008790238,  	0.003542618,  	0.0011708187,  	0.0003343110,  	9.181052e-05},
	{0.02019796,  	0.03066531,  	0.03341075,  	0.02708524,  	0.01681453,  	0.008140744,  	0.003127764,  	0.0009833417,  	0.0002698614,  	7.471549e-05},
	{0.02034031,  	0.03069718,  	0.03314100,  	0.02653637,  	0.01622749,  	0.007717614,  	0.002899693,  	0.0008850159,  	0.0002342358,  	6.320368e-05},
	{0.01891187,  	0.02865354,  	0.03114725,  	0.02522470,  	0.01570111,  	0.007659463,  	0.002970619,  	0.0009359500,  	0.0002526771,  	6.695333e-05},
	{0.01746558,  	0.02660378,  	0.02918189,  	0.02397508,  	0.01524437,  	0.007655413,  	0.003074743,  	0.0010043440,  	0.0002796695,  	7.533102e-05}
};

double jointPG[8][10] ={
	{0.01282095,	0.01890120,	0.01993705,	0.01571705,	0.009782261,	0.005191671,	0.002691798,	0.001654773,	0.001214986,	0.0008377835},
	{0.01564122,	0.02314193,	0.02453750,	0.01947096,	0.012195836,	0.006488151,	0.003340786,	0.002023886,	0.001466667,	0.0009962073},
	{0.01780546,	0.02637817,	0.02802621,	0.02230770,	0.014029451,	0.007492171,	0.003860250,	0.002330549,	0.001679664,	0.0011291316},
	{0.01958025,	0.02876465,	0.03017232,	0.02360213,	0.014544632,	0.007622512,	0.003897838,	0.002378630,	0.001737877,	0.0011750759},
	{0.02157550,	0.03128484,	0.03214381,	0.02440413,	0.014471932,	0.007281909,	0.003633972,	0.002237180,	0.001667698,	0.0011461562},
	{0.02229094,	0.03218090,	0.03282977,	0.02465891,	0.014407394,	0.007117145,	0.003487906,	0.002125674,	0.001585466,	0.0010991210},
	{0.02075700,	0.03011903,	0.03098697,	0.02358301,	0.014037971,	0.007083045,	0.003508268,	0.002114442,	0.001557243,	0.0010763121},
	{0.01905084,	0.02779263,	0.02885341,	0.02227759,	0.013545047,	0.007019597,	0.003561619,	0.002171509,	0.001602700,	0.0011041007}
};

double transitionPG[8][8] = {
	{0.0330,    0.0141,    0.0201,    0.0012,    0.0212,    0.0119,    0.0361,    0.0246},
    {0.0284,    0.0048,    0.0100,    0.0103,    0.0014,    0.0031,    0.0077,    0.0108},
    {0.0310,    0.0153,    0.0074,    0.0186,    0.0189,    0.0015,    0.0203,    0.0129},
    {0.0114,    0.0077,    0.0162,    0.0084,    0.0194,    0.0084,    0.0014,    0.0169},
    {0.0229,    0.0196,    0.0575,    0.0325,    0.0580,    0.0208,    0.0239,    0.0028},
    {0.0010,    0.0040,    0.0072,    0.0057,    0.0349,    0.0071,    0.0122,    0.0053},
    {0.0146,    0.0026,    0.0071,    0.0095,    0.0618,    0.0174,    0.0103,    0.0141},
    {0.0200,    0.0084,    0.0005,    0.0036,    0.0224,    0.0072,    0.0253,    0.0052}
};

double transitionPS[8][8] = {
	{0.0029,    0.0106,    0.0238,    0.0060,    0.0128,    0.0096,    0.0618,    0.0188},
    {0.0338,    0.0007,    0.0097,    0.0093,    0.0062,    0.0029,    0.0182,    0.0066},
    {0.0472,    0.0291,    0.0031,    0.0097,    0.0250,    0.0059,    0.0284,    0.0174},
    {0.0115,    0.0113,    0.0366,    0.0019,    0.0084,    0.0072,    0.0031,    0.0015},
    {0.0041,    0.0109,    0.0538,    0.0421,    0.0147,    0.0154,    0.0278,    0.0077},
    {0.0019,    0.0013,    0.0175,    0.0043,    0.0384,    0.0016,    0.0129,    0.0072},
    {0.0331,    0.0119,    0.0175,    0.0072,    0.0658,    0.0353,    0.0021,    0.0119},
    {0.0118,    0.0116,    0.0037,    0.0010,    0.0053,    0.0072,    0.0305,    0.0012}
};


int ProbabilitySeparator::getAngleDirection(ComplexNumber vec)
{
	double pi_8 = imago::PI / 8.0;
	double angle = vec.getAngle();
	int retVal = 0;
	if(angle < 0)
		angle  += 2 * imago::PI;
		
	if(angle < pi_8 || angle >= 15.0 * pi_8)
		retVal =  0;//"E";
	else
		if(angle >= pi_8 && angle < 3.0 * pi_8)
			retVal =  1;// "NE";
		else
			if(angle >= 3.0 * pi_8 && angle < pi_8 * 5.0)
				retVal =  2; // "N";
			else
				if(angle >= pi_8 * 5.0 && angle < pi_8 * 7.0)
					retVal =  3; // "NW";
				else
					if(angle >= pi_8 * 7.0 && angle < pi_8 * 9.0)
						retVal =  4; // "W";
		
	if(angle >= 9.0 * pi_8 && angle < 11.0 * pi_8)
			retVal =  5; // "SW";
		else
			if(angle >= 11.0 * pi_8 && angle < pi_8 * 13.0)
				retVal =  6; // "S";
			else
				if(angle >= pi_8 * 13.0 && angle < pi_8 * 15.0)
					retVal =  7; // "SE";
	return retVal;
}

void ProbabilitySeparator::CalculateProbabilities(const Settings& vars, 
	        Image& seg, double& char_probability, double& bond_probability, 
			double char_apriory, double bond_apriory)
{
	ComplexContour contour  = ComplexContour::RetrieveContour(vars, seg);
	
	if(vars.p_estimator.UsePerimeterNormalization)
		contour.NormalizeByPerimeter();
	else
		contour.Normalize();

	double bond_prob = 1.0,
		char_prob = 1.0;

	for(int i = 0; i < contour.Size(); i++)
	{
		imago::ComplexNumber cn = contour.getContour(i);

		int binD = getAngleDirection(cn);
		int binS = ((int)(cn.getRadius() * 10)) % 10;
		int binD2 = getAngleDirection(contour.getContour(i+1));
		if(vars.p_estimator.UsePerimeterNormalization)
		{
			bond_prob *= jointPG[binD][binS];
			char_prob *= jointPS[binD][binS];
		}
		else
		{
			bond_prob *= jointPGMax[binD][binS];
			char_prob *= jointPSMax[binD][binS];
		}
		bond_prob *= transitionPG[binD][binD2];
		char_prob *= transitionPS[binD][binD2];
	}

	char_prob *= char_apriory;
	bond_prob *= bond_apriory;

	char_probability = char_prob / (char_prob + bond_prob);
	bond_probability = bond_prob / (char_prob + bond_prob);
}